package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.settlement.enums.OrderSourceEnum;
import com.tiancheng.trade.settlement.enums.PaymentChannelEnum;
import com.tiancheng.trade.settlement.mapper.settlement.SettlementSituationMapper;
import com.tiancheng.trade.settlement.model.settlement.SettlementSituation;
import com.tiancheng.trade.settlement.service.settlement.ISettlementSituation;
import com.tiancheng.trade.settlement.util.ExcelUtil;
import com.tiancheng.trade.settlement.util.ObjectConvertUtil;
import com.tiancheng.trade.settlement.vo.settlement.admin.SettlementSituationQueryVO;
import com.tiancheng.trade.settlement.vo.settlement.admin.res.SettlementSituationResVO;
import com.tiancheng.trade.settlement.vo.settlement.export.DiffOrderExportVO;
import com.tiancheng.trade.settlement.vo.settlement.export.SettlementSituationExportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

/**
 * 清分情况
 */
@Service
@Slf4j
public class SettlementSituationService implements ISettlementSituation {

    @Autowired
    SettlementSituationMapper settlementSituationMapper;


    /**
     * 更新清分情况报表数据
     *
     * @param settlementSituationQueryVO
     * @return
     */
    public Map<String, Object> updateReport(SettlementSituationQueryVO settlementSituationQueryVO) {
        String reportTime = settlementSituationQueryVO.getReportTime();
        Map<String, Object> dataMap = new HashMap<>();
        if (StringUtils.isNotEmpty(reportTime)) {
            settlementSituationMapper.deleteSituation(reportTime);
            settlementSituationMapper.insertBatch(reportTime);
            SettlementSituationQueryVO vo = new SettlementSituationQueryVO();
            vo.setReportTime(reportTime);
            rtnDateMap(dataMap, vo);
        }
        return dataMap;
    }

    /**
     * 分页查询
     *
     * @param settlementSituationQueryVO 查询条件
     * @return
     */
    private PageInfo<SettlementSituationResVO> findPageList(SettlementSituationQueryVO settlementSituationQueryVO) {
        int page = settlementSituationQueryVO.getCurrentPage();
        int limit = settlementSituationQueryVO.getPageSize();
        QueryWrapper<SettlementSituation> conditions = new QueryWrapper<>();
        if (StringUtils.isNotBlank(settlementSituationQueryVO.getMerchantName())) {
            conditions.eq("merchant_name", settlementSituationQueryVO.getMerchantName());
        }
        if (StringUtils.isNotBlank(settlementSituationQueryVO.getOrderSource())) {
            conditions.eq("order_source", settlementSituationQueryVO.getOrderSource());
        }
        if (StringUtils.isNotBlank(settlementSituationQueryVO.getReportTime())) {
            conditions.eq("period", settlementSituationQueryVO.getReportTime());
        }
        PageInfo<SettlementSituation> pageInfo = settlementSituationMapper.find(conditions, page, limit);
        PageInfo<SettlementSituationResVO> pageRes = new PageInfo<>();
        List<SettlementSituationResVO> listRes = new ArrayList<>();
        pageInfo.getList().stream().forEach(obj -> {
            SettlementSituationResVO resVO = ObjectConvertUtil.convert(obj, SettlementSituationResVO.class).get();
            resVO.setOrderSourceCn(OrderSourceEnum.getDesc(obj.getOrderSource()));
            listRes.add(resVO);
        });
        pageRes.setPagination(pageInfo.getPagination());
        pageRes.setList(listRes);
        return pageRes;
    }

    @Override
    public Map<String, Object> query(SettlementSituationQueryVO settlementSituationQueryVO) {
        Map<String, Object> dataMap = new HashMap<>();
        if (!StringUtils.isEmpty(settlementSituationQueryVO.getReportTime())) {
            PageInfo<SettlementSituationResVO> pageRes = this.findPageList(settlementSituationQueryVO);
            if (pageRes == null || pageRes.getList().isEmpty()) {
                settlementSituationMapper.insertBatch(settlementSituationQueryVO.getReportTime());
            }
            rtnDateMap(dataMap, settlementSituationQueryVO);
        }
        return dataMap;
    }

    private void rtnDateMap(Map<String, Object> dataMap, SettlementSituationQueryVO settlementSituationQueryVO) {
        PageInfo<SettlementSituationResVO> page = this.findPageList(settlementSituationQueryVO);
        if (null != page && !page.getList().isEmpty()) {
            dataMap.put("dataList", page);
            dataMap.put("statisticsTime", page.getList().get(0).getPeriod());
            dataMap.put("generationTime", page.getList().get(0).getReportGenerationDate());
        }
    }

    @Override
    public void export(SettlementSituationQueryVO settlementSituationQueryVO, HttpServletRequest request, HttpServletResponse response) throws IOException {

        QueryWrapper<SettlementSituation> conditions = new QueryWrapper<>();
        conditions.select("merchant_name", "product_name", "order_source", "period", "clear_amount", "merchant_amount", "tengyun_amount", "service_charge", "tengyun_receivable", "tengyun_actual_entry", "merchant_actual_entry", "tengyun_difference", "merchant_difference");
        if (StringUtils.isNotBlank(settlementSituationQueryVO.getMerchantName())) {
            conditions.eq("merchant_name", settlementSituationQueryVO.getMerchantName());
        }
        if (StringUtils.isNotBlank(settlementSituationQueryVO.getOrderSource())) {
            conditions.eq("order_source", settlementSituationQueryVO.getOrderSource());
        }
        if (StringUtils.isNotBlank(settlementSituationQueryVO.getReportTime())) {
            conditions.eq("period", settlementSituationQueryVO.getReportTime());
        }
        List<SettlementSituation> list = settlementSituationMapper.selectList(conditions);
        List<SettlementSituationExportVO> listRes = new ArrayList<>();
        BigDecimal bigNum1 = new BigDecimal(100);
        list.forEach(obj -> {
            SettlementSituationExportVO resVO = ObjectConvertUtil.convert(obj, SettlementSituationExportVO.class).get();
            if (null != obj.getClearAmount()) {
                BigDecimal hotelRate = new BigDecimal(obj.getClearAmount().toString());
                resVO.setClearAmount(hotelRate.divide(bigNum1).toString());
            }
            if (null != obj.getMerchantAmount()) {
                BigDecimal merchantAmount = new BigDecimal(obj.getMerchantAmount().toString());
                resVO.setMerchantAmount(merchantAmount.divide(bigNum1).toString());
            }
            if (null != obj.getTengyunAmount()) {
                BigDecimal tengyunAmount = new BigDecimal(obj.getTengyunAmount().toString());
                resVO.setTengyunAmount(tengyunAmount.divide(bigNum1).toString());
            }
            if (null != obj.getServiceCharge()) {
                BigDecimal serviceCharge = new BigDecimal(obj.getServiceCharge().toString());
                resVO.setServiceCharge(serviceCharge.divide(bigNum1).toString());
            }
            if (null != obj.getTengyunReceivable()) {
                BigDecimal tengyunReceivable = new BigDecimal(obj.getTengyunReceivable().toString());
                resVO.setTengyunReceivable(tengyunReceivable.divide(bigNum1).toString());
            }
            if (null != obj.getTengyunActualEntry()) {
                BigDecimal tengyunActualEntry = new BigDecimal(obj.getTengyunActualEntry().toString());
                resVO.setTengyunActualEntry(tengyunActualEntry.divide(bigNum1).toString());
            }
            if (null != obj.getMerchantActualEntry()) {
                BigDecimal merchantActualEntry = new BigDecimal(obj.getMerchantActualEntry().toString());
                resVO.setMerchantActualEntry(merchantActualEntry.divide(bigNum1).toString());
            }
            if (null != obj.getTengyunDifference()) {
                BigDecimal tengyunDifference = new BigDecimal(obj.getTengyunDifference().toString());
                resVO.setTengyunDifference(tengyunDifference.divide(bigNum1).toString());
            }
            if (null != obj.getMerchantDifference()) {
                BigDecimal merchantDifference = new BigDecimal(obj.getMerchantDifference().toString());
                resVO.setMerchantDifference(merchantDifference.divide(bigNum1).toString());
            }
            resVO.setOrderSourceCn(OrderSourceEnum.getDesc(obj.getOrderSource()));
            listRes.add(resVO);
        });

        String[] title = {"商户名称", "商品名称", "场景", "周期", "清分金额(￥)", "商户部分(￥)", "腾云部分(￥)", "手续费(￥)", "腾云应收(￥)", "腾云实际入账金额(￥)", "商户实际入账(￥)", "腾云差额(￥)", "商户差额(￥)"};
        if (CollectionUtils.isNotEmpty(listRes)) {
            List<Map<String, Object>> mapList = exportConvert(listRes);
            String fileName = "清分情况表.xlsx";
            Workbook workbook = ExcelUtil.buildWorkbook("清分情况表", title, mapList);
            ExcelUtil.exportExcle(request, response, workbook, fileName);
        }
    }

    /**
     * 数据转换
     *
     * @param list
     * @return
     */
    private List<Map<String, Object>> exportConvert(List<SettlementSituationExportVO> list) {
        List<Map<String, Object>> list_map = new ArrayList<Map<String, Object>>();
        try {
            for (SettlementSituationExportVO t : list) {
                Field[] fields = t.getClass().getDeclaredFields();
                Map<String, Object> m = new LinkedHashMap<String, Object>();
                for (Field field : fields) {
                    String keyName = field.getName();
                    PropertyDescriptor pd = new PropertyDescriptor(keyName, t.getClass());
                    Method getMethod = pd.getReadMethod();// 获得getter方法
                    Object o = getMethod.invoke(t);// 执行get方法返回一个Object
                    m.put(keyName, o);
                }
                list_map.add(m);
            }
            return list_map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void diffOrderExport(String reportTime, HttpServletRequest request, HttpServletResponse response) {
        List<DiffOrderExportVO> list = settlementSituationMapper.diffOrderExport(reportTime);
        BigDecimal num = new BigDecimal(100);
        list.forEach(diff -> {
            if (StringUtils.isNotEmpty(diff.getOrderSource())) {
                diff.setOrderSource(OrderSourceEnum.getDesc(diff.getOrderSource()));
            }
            if (StringUtils.isNotEmpty(diff.getPayChannelCode())) {
                diff.setPayChannelCode(PaymentChannelEnum.getDesc(diff.getPayChannelCode()));
            }
            if (StringUtils.isNotEmpty(diff.getVerifiedAmount())) {
                BigDecimal verifiedAmount = new BigDecimal(diff.getVerifiedAmount());
                diff.setVerifiedAmount(verifiedAmount.divide(num).toString());
            }
        });
        List<Map<String, Object>> mapList = listConvert(list);
        String date = DateTimeUtil.getSystemDate("yyyy-MM-dd");
        String fileName = "差额订单明细" + date + ".xlsx";

        String[] title = {"主订单号", "子订单号",
                "渠道支付订单号", "商品编码", "商品名称",
                "业务场景", "商户名称", "商户编码", "清分渠道"
                , "清分金额", "交易时间", "核销时间"};
        Workbook workbook;
        try {
            workbook = ExcelUtil.buildWorkbook(fileName, title, mapList);
            ExcelUtil.exportExcle(request, response, workbook, fileName);
        } catch (IOException e) {
            log.info("导出差额明细数据出现异常{}", e.getMessage());
            e.printStackTrace();
        }

    }

    /**
     * 数据转换
     *
     * @param list
     * @return
     */
    private List<Map<String, Object>> listConvert(List<DiffOrderExportVO> list) {
        List<Map<String, Object>> list_map = new ArrayList<Map<String, Object>>();
        try {
            for (DiffOrderExportVO t : list) {
                Field[] fields = t.getClass().getDeclaredFields();
                Map<String, Object> m = new LinkedHashMap<String, Object>();
                for (Field field : fields) {
                    String keyName = field.getName();
                    PropertyDescriptor pd = new PropertyDescriptor(keyName, t.getClass());
                    Method getMethod = pd.getReadMethod();// 获得getter方法
                    Object o = getMethod.invoke(t);// 执行get方法返回一个Object
                    m.put(keyName, o);
                }
                list_map.add(m);
            }
            return list_map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
